﻿using System;
using System.Windows;

namespace Microsoft.Popfly.GameCreator.GameEngine.Behaviors
{
    // To move away, simply call reverse on a move toward behavior before executing it
    // TODO: if we really want to become perf conscious we could make a moveaway that calls the non-anti bounce version of
    // calculateoffsettoward directly.
    #region MoveTowardBehaviors
    #region MoveTowardActors
    abstract class MoveTowardActorsBehavior : XYMoveBehavior
    {
        protected string m_actorName;
        protected Game m_game;
        public MoveTowardActorsBehavior(Game game, BehaviorOwner owner, string targetName, double offset)
            : base(owner, offset)
        {
            m_game = game;
            m_actorName = targetName;
        }
    }

    class MoveTowardActorsAccelerationBehavior : MoveTowardActorsBehavior
    {
        public MoveTowardActorsAccelerationBehavior(Game game, BehaviorOwner owner, string targetName, double acceleration) : base(game, owner, targetName, acceleration) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            Actor moveToward = MoveHelpers.FindClosestActor(m_owner.Scene.GetActors(m_actorName), m_owner.GetCenterX(), m_owner.GetCenterY());
            if (moveToward != null)
            {
                double incrXAccel, incrYAccel;

                MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), moveToward.GetObjectCenter(), m_offset, out incrXAccel, out incrYAccel);
                m_owner.XAcceleration += incrXAccel;
                m_owner.YAcceleration += incrYAccel;
            }
        }
    }
    class MoveTowardActorsMaxSpeedBehavior : MoveTowardActorsBehavior
    {
        public MoveTowardActorsMaxSpeedBehavior(Game game, BehaviorOwner owner, string targetName, double maxSpeed) : base(game, owner, targetName, maxSpeed) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            Actor moveToward = MoveHelpers.FindClosestActor(m_owner.Scene.GetActors(m_actorName), m_owner.GetCenterX(), m_owner.GetCenterY());
            if (moveToward != null)
            {
                double incrXAccel, incrYAccel;
                MoveHelpers.MaxSpeedMoveToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), moveToward.GetObjectCenter(), m_offset, m_owner.XDrag, m_owner.YDrag, out incrXAccel, out incrYAccel);
                m_owner.XAcceleration += incrXAccel;
                m_owner.YAcceleration += incrYAccel;
            }
        }
    }
    class MoveTowardActorsVelocityBehavior : MoveTowardActorsBehavior
    {
        public MoveTowardActorsVelocityBehavior(Game game, BehaviorOwner owner, string targetName, double velocity) : base(game, owner, targetName, velocity) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            Actor moveToward = MoveHelpers.FindClosestActor(m_owner.Scene.GetActors(m_actorName), m_owner.GetCenterX(), m_owner.GetCenterY());
            if (moveToward != null)
            {
                double incrXVel, incrYVel;
                MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), moveToward.GetObjectCenter(), m_offset, out incrXVel, out incrYVel);
                m_owner.XVelocity += incrXVel;
                m_owner.YVelocity += incrYVel;
            }
        }
    }
    #endregion 

    #region MoveTowardActor
    abstract class MoveTowardActorBehavior : XYMoveBehavior
    {
        protected Actor m_target;
        protected Game m_game;
        public MoveTowardActorBehavior(Game game, BehaviorOwner owner, Actor target, double offset) : base(owner, offset)
        {
            m_game = game;
            m_target = target; 
        }
    }
    class MoveTowardActorAccelerationBehavior : MoveTowardActorBehavior
    {
        public MoveTowardActorAccelerationBehavior(Game game, BehaviorOwner owner, Actor target, double acceleration) : base(game, owner, target, acceleration) { }
        
        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            if (!m_target.Removed)
            {
                double incrXAccel, incrYAccel;
                MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_target.GetObjectCenter(), m_offset, out incrXAccel, out incrYAccel);
                m_owner.XAcceleration += incrXAccel;
                m_owner.YAcceleration += incrYAccel;
            }
        }
    }
    class MoveTowardActorMaxSpeedBehavior : MoveTowardActorBehavior
    {
        public MoveTowardActorMaxSpeedBehavior(Game game, BehaviorOwner owner, Actor target, double maxSpeed) : base(game, owner, target, maxSpeed) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            if (!m_target.Removed)
            {
                double incrXAccel, incrYAccel;
                MoveHelpers.MaxSpeedMoveToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_target.GetObjectCenter(), m_offset, m_owner.XDrag, m_owner.YDrag, out incrXAccel, out incrYAccel);
                m_owner.XAcceleration += incrXAccel;
                m_owner.YAcceleration += incrYAccel;
            }
        }
    }
    class MoveTowardActorVelocityBehavior : MoveTowardActorBehavior
    {
        public MoveTowardActorVelocityBehavior(Game game, BehaviorOwner owner, Actor target, double velocity) : base(game, owner, target, velocity) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            if (!m_target.Removed)
            {
                double incrXVel, incrYVel;
                MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_target.GetObjectCenter(), m_offset, out incrXVel, out incrYVel);
                m_owner.XVelocity += incrXVel;
                m_owner.YVelocity += incrYVel;
            }
        }
    }
    #endregion 
    
    
    #region MoveTowardMouse
    abstract class MoveTowardMouseBehavior : XYMoveBehavior
    {
        protected Game m_game;
        public MoveTowardMouseBehavior(Game game, BehaviorOwner owner, double offset)
            : base(owner, offset)
        {
            m_game = game;
        }
    }


    class MoveTowardMouseXAccelerationBehavior : XMoveBehavior
    {
        private Game m_game;
        public MoveTowardMouseXAccelerationBehavior(Game game, BehaviorOwner owner, double acceleration) : base(owner, acceleration) 
        {
            m_game = game;
        }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_owner.XAcceleration += MoveHelpers.CalculateSingleDimensionOffsetAntiBounce(m_game.DeltaTimeInSeconds, m_owner.GetCenterX(), m_game.MousePosition.X, m_offset);
        }
    }

    class MoveTowardMouseYAccelerationBehavior : YMoveBehavior
    {
        private Game m_game;
        public MoveTowardMouseYAccelerationBehavior(Game game, BehaviorOwner owner, double acceleration) : base(owner, acceleration) 
        {
            m_game = game;
        }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_owner.YAcceleration += MoveHelpers.CalculateSingleDimensionOffsetAntiBounce(m_game.DeltaTimeInSeconds, m_owner.GetCenterY(), m_game.MousePosition.Y, m_offset);
        }
    }

    class MoveTowardMouseXMaxSpeedBehavior : XMoveBehavior
    {
        private Game m_game;
        public MoveTowardMouseXMaxSpeedBehavior(Game game, BehaviorOwner owner, double maxSpeed) : base(owner, maxSpeed) 
        {
            m_game = game;
        }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_owner.XAcceleration += MoveHelpers.MaxSpeedSingleDimensionMoveTowardAntiBounce(m_game.DeltaTimeInSeconds, m_owner.GetCenterX(), m_game.MousePosition.X, m_offset, m_owner.XDrag);
        }
    }

    class MoveTowardMouseYMaxSpeedBehavior : YMoveBehavior
    {
        private Game m_game;
        public MoveTowardMouseYMaxSpeedBehavior(Game game, BehaviorOwner owner, double maxSpeed) : base(owner, maxSpeed)
        {
            m_game = game;
        }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_owner.YAcceleration += MoveHelpers.MaxSpeedSingleDimensionMoveTowardAntiBounce(m_game.DeltaTimeInSeconds, m_owner.GetCenterY(), m_game.MousePosition.Y, m_offset, m_owner.YDrag);
        }
    }

    class MoveTowardMouseXVelocityBehavior : XMoveBehavior
    {
        private Game m_game;
        public MoveTowardMouseXVelocityBehavior(Game game, BehaviorOwner owner, double velocity) : base(owner, velocity) 
        {
            m_game = game;
        }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_owner.XVelocity += MoveHelpers.CalculateSingleDimensionOffsetAntiBounce(m_game.DeltaTimeInSeconds, m_owner.GetCenterX(), m_game.MousePosition.X, m_offset);
        }
    }

    class MoveTowardMouseYVelocityBehavior : YMoveBehavior
    {
        private Game m_game;
        public MoveTowardMouseYVelocityBehavior(Game game, BehaviorOwner owner, double velocity) : base(owner, velocity) 
        {
            m_game = game;
        }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            m_owner.YVelocity += MoveHelpers.CalculateSingleDimensionOffsetAntiBounce(m_game.DeltaTimeInSeconds, m_owner.GetCenterY(), m_game.MousePosition.Y, m_offset);
        }
    }

    class MoveTowardMouseAccelerationBehavior : MoveTowardMouseBehavior
    {
        public MoveTowardMouseAccelerationBehavior(Game game, BehaviorOwner owner, double acceleration) : base(game, owner, acceleration) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_game.MousePosition, m_offset, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += incrXAccel;
            m_owner.YAcceleration += incrYAccel;
        }
    }

    class MoveTowardMouseMaxSpeedBehavior : MoveTowardMouseBehavior
    {
        public MoveTowardMouseMaxSpeedBehavior(Game game, BehaviorOwner owner, double maxSpeed) : base(game, owner, maxSpeed) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.MaxSpeedMoveToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_game.MousePosition, m_offset, m_owner.XDrag, m_owner.YDrag, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += incrXAccel;
            m_owner.YAcceleration += incrYAccel;
        }
    }

    class MoveTowardMouseVelocityBehavior : MoveTowardMouseBehavior
    {
        public MoveTowardMouseVelocityBehavior(Game game, BehaviorOwner owner, double velocity) : base(game, owner, velocity) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXVel, incrYVel;
            MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_game.MousePosition, m_offset, out incrXVel, out incrYVel);
            m_owner.XVelocity += incrXVel;
            m_owner.YVelocity += incrYVel;
            
        }
    }
    #endregion

    #region MoveTowardPoint
    abstract class MoveTowardPointBehavior : XYMoveBehavior
    {
        protected Point m_target;
        protected Game m_game;
        public MoveTowardPointBehavior(Game game, BehaviorOwner owner, Point target, double offset)
            : base(owner, offset)
        {
            m_game = game;
            m_target = target;
        }
    }

    class MoveTowardPointAccelerationBehavior : MoveTowardPointBehavior
    {
        public MoveTowardPointAccelerationBehavior(Game game, BehaviorOwner owner, Point target, double acceleration) : base(game, owner, target, acceleration){ }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_target, m_offset, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += incrXAccel;
            m_owner.YAcceleration += incrYAccel;
        }
    }

    class MoveTowardPointMaxSpeedBehavior : MoveTowardPointBehavior
    {
        public MoveTowardPointMaxSpeedBehavior(Game game, BehaviorOwner owner, Point target, double maxSpeed) : base(game, owner, target, maxSpeed) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.MaxSpeedMoveToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_target, m_offset, m_owner.XDrag, m_owner.YDrag, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += incrXAccel;
            m_owner.YAcceleration += incrYAccel;
        }
    }

    class MoveTowardPointVelocityBehavior : MoveTowardPointBehavior
    {
        public MoveTowardPointVelocityBehavior(Game game, BehaviorOwner owner, Point target, double velocity) : base(game, owner, target, velocity) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXVel, incrYVel;
            MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_target, m_offset, out incrXVel, out incrYVel);
            m_owner.XVelocity += incrXVel;
            m_owner.YVelocity += incrYVel;
        }
    }
    #endregion 
    #endregion 

    // Move right makes use of the fact that you just switch (X, Y) to (Y, -X) to get the right angle of a vector
    // To move left, simply call reverse on this behavior before executing it
    #region MoveRightBehaviors  
    #region MoveRightFromActors

    class MoveRightFromActorsAccelerationBehavior : MoveTowardActorsBehavior
    {
        public MoveRightFromActorsAccelerationBehavior(BehaviorOwner owner, string targetName, double acceleration) : base(null, owner, targetName, acceleration) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            Actor moveToward = MoveHelpers.FindClosestActor(m_owner.Scene.GetActors(m_actorName), m_owner.GetCenterX(), m_owner.GetCenterY());
            if (moveToward != null)
            {
                double incrXAccel, incrYAccel;
                MoveHelpers.CalculateOffsetToward(m_owner.GetObjectCenter(), moveToward.GetObjectCenter(), m_offset, out incrXAccel, out incrYAccel);
                m_owner.XAcceleration += - incrYAccel;
                m_owner.YAcceleration += incrXAccel;
            }
        }
    }
    class MoveRightFromActorsMaxSpeedBehavior : MoveTowardActorsBehavior
    {
        public MoveRightFromActorsMaxSpeedBehavior(BehaviorOwner owner, string targetName, double maxSpeed) : base(null, owner, targetName, maxSpeed) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            Actor moveToward = MoveHelpers.FindClosestActor(m_owner.Scene.GetActors(m_actorName), m_owner.GetCenterX(), m_owner.GetCenterY());
            if (moveToward != null)
            {
                double incrXAccel, incrYAccel;
                MoveHelpers.MaxSpeedMoveToward(m_owner.GetObjectCenter(), moveToward.GetObjectCenter(), m_offset, m_owner.XDrag, m_owner.YDrag, out incrXAccel, out incrYAccel);
                m_owner.XAcceleration += - incrYAccel;
                m_owner.YAcceleration += incrXAccel;
            }
        }
    }
    class MoveRightFromActorsVelocityBehavior : MoveTowardActorsBehavior
    {
        public MoveRightFromActorsVelocityBehavior(BehaviorOwner owner, string targetName, double velocity) : base(null, owner, targetName, velocity) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            Actor moveToward = MoveHelpers.FindClosestActor(m_owner.Scene.GetActors(m_actorName), m_owner.GetCenterX(), m_owner.GetCenterY());
            if (moveToward != null)
            {
                double incrXVel, incrYVel;
                MoveHelpers.CalculateOffsetToward(m_owner.GetObjectCenter(), moveToward.GetObjectCenter(), m_offset, out incrXVel, out incrYVel);
                m_owner.XVelocity += - incrYVel;
                m_owner.YVelocity += incrXVel;
            }
        }
    }
    #endregion 

    #region MoveRightFromActor

    class MoveRightFromActorAccelerationBehavior : MoveTowardActorBehavior
    {
        public MoveRightFromActorAccelerationBehavior(BehaviorOwner owner, Actor target, double acceleration) : base(null, owner, target, acceleration) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.CalculateOffsetToward(m_owner.GetObjectCenter(), m_target.GetObjectCenter(), m_offset, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += - incrYAccel;
            m_owner.YAcceleration += incrXAccel;
        }
    }
    class MoveRightFromActorMaxSpeedBehavior : MoveTowardActorBehavior
    {
        public MoveRightFromActorMaxSpeedBehavior(BehaviorOwner owner, Actor target, double maxSpeed) : base(null, owner, target, maxSpeed) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.MaxSpeedMoveToward(m_owner.GetObjectCenter(), m_target.GetObjectCenter(), m_offset, m_owner.XDrag, m_owner.YDrag, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += - incrYAccel;
            m_owner.YAcceleration += incrXAccel;
        }
    }
    class MoveRightFromActorVelocityBehavior : MoveTowardActorBehavior
    {
        public MoveRightFromActorVelocityBehavior(BehaviorOwner owner, Actor target, double velocity) : base(null, owner, target, velocity) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXVel, incrYVel;
            MoveHelpers.CalculateOffsetToward(m_owner.GetObjectCenter(), m_target.GetObjectCenter(), m_offset, out incrXVel, out incrYVel);
            m_owner.XVelocity += - incrYVel;
            m_owner.YVelocity += incrXVel;
        }
    }
    #endregion 

    #region MoveRightFromMouse
    class MoveRightFromMouseAccelerationBehavior : MoveTowardMouseBehavior
    {
        public MoveRightFromMouseAccelerationBehavior(Game game, BehaviorOwner owner, double acceleration) : base(game, owner, acceleration) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.CalculateOffsetToward(m_owner.GetObjectCenter(), m_game.MousePosition, m_offset, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += - incrYAccel;
            m_owner.YAcceleration += incrXAccel;
        }
    }

    class MoveRightFromMouseMaxSpeedBehavior : MoveTowardMouseBehavior
    {
        public MoveRightFromMouseMaxSpeedBehavior(Game game, BehaviorOwner owner, double maxSpeed) : base(game, owner, maxSpeed) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.MaxSpeedMoveToward(m_owner.GetObjectCenter(), m_game.MousePosition, m_offset, m_owner.XDrag, m_owner.YDrag, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += - incrYAccel;
            m_owner.YAcceleration += incrXAccel;
        }
    }

    class MoveRightFromMouseVelocityBehavior : MoveTowardMouseBehavior
    {
        public MoveRightFromMouseVelocityBehavior(Game game, BehaviorOwner owner, double velocity) : base(game, owner, velocity) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXVel, incrYVel;
            MoveHelpers.CalculateOffsetToward(m_owner.GetObjectCenter(), m_game.MousePosition, m_offset, out incrXVel, out incrYVel);
            m_owner.XVelocity += - incrYVel;
            m_owner.YVelocity += incrXVel;

        }
    }
    #endregion

    #region MoveRightFromPoint


    class MoveRightFromPointAccelerationBehavior : MoveTowardPointBehavior
    {
        public MoveRightFromPointAccelerationBehavior(BehaviorOwner owner, Point target, double acceleration) : base(null, owner, target, acceleration) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.CalculateOffsetToward(m_owner.GetObjectCenter(), m_target, m_offset, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += - incrYAccel;
            m_owner.YAcceleration += incrXAccel;
        }
    }

    class MoveRightFromPointMaxSpeedBehavior : MoveTowardPointBehavior
    {
        public MoveRightFromPointMaxSpeedBehavior(BehaviorOwner owner, Point target, double maxSpeed) : base(null, owner, target, maxSpeed) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.MaxSpeedMoveToward(m_owner.GetObjectCenter(), m_target, m_offset, m_owner.XDrag, m_owner.YDrag, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += - incrYAccel;
            m_owner.YAcceleration += incrXAccel;
        }
    }

    class MoveRightFromPointVelocityBehavior : MoveTowardPointBehavior
    {
        public MoveRightFromPointVelocityBehavior(BehaviorOwner owner, Point target, double velocity) : base(null, owner, target, velocity) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXVel, incrYVel;
            MoveHelpers.CalculateOffsetToward(m_owner.GetObjectCenter(), m_target, m_offset, out incrXVel, out incrYVel);
            m_owner.XVelocity += - incrYVel;
            m_owner.YVelocity += incrXVel;
        }
    }
    #endregion 
    #endregion // Move Right From Behaviors

    #region MoveAngleFromBehaviors
    #region MoveAngleFromActors

    abstract class MoveAngleFromActorsBehavior : MoveTowardActorsBehavior
    {
        protected double m_radians;
        public MoveAngleFromActorsBehavior(Game game, BehaviorOwner owner, string targetName, double offset, double radians)
            : base(game, owner, targetName, offset)
        {
            m_radians = radians;
        }
    }

    class MoveAngleFromActorsAccelerationBehavior : MoveAngleFromActorsBehavior
    {
        public MoveAngleFromActorsAccelerationBehavior(Game game, BehaviorOwner owner, string targetName, double acceleration, double radians) : base(game, owner, targetName, acceleration, radians) { }


        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            Actor moveToward = MoveHelpers.FindClosestActor(m_owner.Scene.GetActors(m_actorName), m_owner.GetCenterX(), m_owner.GetCenterY());
            if (moveToward != null)
            {
                double incrXAccel, incrYAccel;

                MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), moveToward.GetObjectCenter(), m_offset, out incrXAccel, out incrYAccel);
                MathUtils.RotateRadians(incrXAccel, incrYAccel, m_radians, out incrXAccel, out incrYAccel);
                m_owner.XAcceleration += incrXAccel;
                m_owner.YAcceleration += incrYAccel;
            }
        }
    }
    class MoveAngleFromActorsMaxSpeedBehavior : MoveAngleFromActorsBehavior
    {
        public MoveAngleFromActorsMaxSpeedBehavior(Game game, BehaviorOwner owner, string targetName, double maxSpeed, double radians) : base(game, owner, targetName, maxSpeed, radians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            Actor moveToward = MoveHelpers.FindClosestActor(m_owner.Scene.GetActors(m_actorName), m_owner.GetCenterX(), m_owner.GetCenterY());
            if (moveToward != null)
            {
                double incrXAccel, incrYAccel;
                MoveHelpers.MaxSpeedMoveToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), moveToward.GetObjectCenter(), m_offset, m_owner.XDrag, m_owner.YDrag, out incrXAccel, out incrYAccel);
                MathUtils.RotateRadians(incrXAccel, incrYAccel, m_radians, out incrXAccel, out incrYAccel);
                m_owner.XAcceleration += incrXAccel;
                m_owner.YAcceleration += incrYAccel;
            }
        }
    }
    class MoveAngleFromActorsVelocityBehavior : MoveAngleFromActorsBehavior
    {
        public MoveAngleFromActorsVelocityBehavior(Game game, BehaviorOwner owner, string targetName, double velocity, double radians) : base(game, owner, targetName, velocity, radians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            Actor moveToward = MoveHelpers.FindClosestActor(m_owner.Scene.GetActors(m_actorName), m_owner.GetCenterX(), m_owner.GetCenterY());
            if (moveToward != null)
            {
                double incrXVel, incrYVel;
                MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), moveToward.GetObjectCenter(), m_offset, out incrXVel, out incrYVel);
                MathUtils.RotateRadians(incrXVel, incrYVel, m_radians, out incrXVel, out incrYVel);
                m_owner.XVelocity += incrXVel;
                m_owner.YVelocity += incrYVel;
            }
        }
    }
    #endregion

    #region MoveAngleFromActor
    abstract class MoveAngleFromActorBehavior : MoveTowardActorBehavior
    {
        protected double m_radians;
        public MoveAngleFromActorBehavior(Game game, BehaviorOwner owner, Actor target, double offset, double radians)
            : base(game, owner, target, offset)
        {
            m_radians = radians;
        }
    }
    class MoveAngleFromActorAccelerationBehavior : MoveAngleFromActorBehavior
    {
        public MoveAngleFromActorAccelerationBehavior(Game game, BehaviorOwner owner, Actor target, double acceleration, double radians) : base(game, owner, target, acceleration, radians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_target.GetObjectCenter(), m_offset, out incrXAccel, out incrYAccel);
            MathUtils.RotateRadians(incrXAccel, incrYAccel, m_radians, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += incrXAccel;
            m_owner.YAcceleration += incrYAccel;
        }
    }
    class MoveAngleFromActorMaxSpeedBehavior : MoveAngleFromActorBehavior
    {
        public MoveAngleFromActorMaxSpeedBehavior(Game game, BehaviorOwner owner, Actor target, double maxSpeed, double radians) : base(game, owner, target, maxSpeed, radians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.MaxSpeedMoveToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_target.GetObjectCenter(), m_offset, m_owner.XDrag, m_owner.YDrag, out incrXAccel, out incrYAccel);
            MathUtils.RotateRadians(incrXAccel, incrYAccel, m_radians, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += incrXAccel;
            m_owner.YAcceleration += incrYAccel;
        }
    }
    class MoveAngleFromActorVelocityBehavior : MoveAngleFromActorBehavior
    {
        public MoveAngleFromActorVelocityBehavior(Game game, BehaviorOwner owner, Actor target, double velocity, double radians) : base(game, owner, target, velocity, radians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXVel, incrYVel;
            MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_target.GetObjectCenter(), m_offset, out incrXVel, out incrYVel);
            MathUtils.RotateRadians(incrXVel, incrYVel, m_radians, out incrXVel, out incrYVel);
            m_owner.XVelocity += incrXVel;
            m_owner.YVelocity += incrYVel;
        }
    }
    #endregion

    #region MoveAngleFromMouse
    abstract class MoveAngleFromMouseBehavior : MoveTowardMouseBehavior
    {
        protected double m_radians;
        public MoveAngleFromMouseBehavior(Game game, BehaviorOwner owner, double offset, double radians)
            : base(game, owner, offset)
        {
            m_radians = radians;
        }
    }

    class MoveAngleFromMouseAccelerationBehavior : MoveAngleFromMouseBehavior
    {
        public MoveAngleFromMouseAccelerationBehavior(Game game, BehaviorOwner owner, double acceleration, double radians) : base(game, owner, acceleration, radians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_game.MousePosition, m_offset, out incrXAccel, out incrYAccel);
            MathUtils.RotateRadians(incrXAccel, incrYAccel, m_radians, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += incrXAccel;
            m_owner.YAcceleration += incrYAccel;
        }
    }

    class MoveAngleFromMouseMaxSpeedBehavior : MoveAngleFromMouseBehavior
    {
        public MoveAngleFromMouseMaxSpeedBehavior(Game game, BehaviorOwner owner, double maxSpeed, double radians) : base(game, owner, maxSpeed, radians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.MaxSpeedMoveToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_game.MousePosition, m_offset, m_owner.XDrag, m_owner.YDrag, out incrXAccel, out incrYAccel);
            MathUtils.RotateRadians(incrXAccel, incrYAccel, m_radians, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += incrXAccel;
            m_owner.YAcceleration += incrYAccel;
        }
    }

    class MoveAngleFromMouseVelocityBehavior : MoveAngleFromMouseBehavior
    {
        public MoveAngleFromMouseVelocityBehavior(Game game, BehaviorOwner owner, double velocity, double radians) : base(game, owner, velocity, radians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXVel, incrYVel;
            MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_game.MousePosition, m_offset, out incrXVel, out incrYVel);
            MathUtils.RotateRadians(incrXVel, incrYVel, m_radians, out incrXVel, out incrYVel);
            m_owner.XVelocity += incrXVel;
            m_owner.YVelocity += incrYVel;

        }
    }
    #endregion

    #region MoveAngleFromPoint
    abstract class MoveAngleFromPointBehavior : MoveTowardPointBehavior
    {
        protected double m_radians;
        public MoveAngleFromPointBehavior(Game game, BehaviorOwner owner, Point target, double offset, double radians)
            : base(game, owner, target, offset)
        {
            m_radians = radians;
        }
    }

    class MoveAngleFromPointAccelerationBehavior : MoveAngleFromPointBehavior
    {
        public MoveAngleFromPointAccelerationBehavior(Game game, BehaviorOwner owner, Point target, double acceleration, double radians) : base(game, owner, target, acceleration, radians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_target, m_offset, out incrXAccel, out incrYAccel);
            MathUtils.RotateRadians(incrXAccel, incrYAccel, m_radians, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += incrXAccel;
            m_owner.YAcceleration += incrYAccel;
        }
    }

    class MoveAngleFromPointMaxSpeedBehavior : MoveAngleFromPointBehavior
    {
        public MoveAngleFromPointMaxSpeedBehavior(Game game, BehaviorOwner owner, Point target, double maxSpeed, double radians) : base(game, owner, target, maxSpeed, radians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXAccel, incrYAccel;
            MoveHelpers.MaxSpeedMoveToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_target, m_offset, m_owner.XDrag, m_owner.YDrag, out incrXAccel, out incrYAccel);
            MathUtils.RotateRadians(incrXAccel, incrYAccel, m_radians, out incrXAccel, out incrYAccel);
            m_owner.XAcceleration += incrXAccel;
            m_owner.YAcceleration += incrYAccel;
        }
    }

    class MoveAngleFromPointVelocityBehavior : MoveAngleFromPointBehavior
    {
        public MoveAngleFromPointVelocityBehavior(Game game, BehaviorOwner owner, Point target, double velocity, double radians) : base(game, owner, target, velocity, radians) { }

        public override void Invoke(BehaviorOwner sender, Microsoft.Popfly.GameCreator.GameEngine.Events.PGCEventArgs args)
        {
            double incrXVel, incrYVel;
            MoveHelpers.CalculateOffsetToward(m_isOriginalDirection, m_game.DeltaTimeInSeconds, m_owner.GetObjectCenter(), m_target, m_offset, out incrXVel, out incrYVel);
            MathUtils.RotateRadians(incrXVel, incrYVel, m_radians, out incrXVel, out incrYVel);
            m_owner.XVelocity += incrXVel;
            m_owner.YVelocity += incrYVel;
        }
    }
    #endregion
    #endregion 
}